package net.lab1024.sa.base.module.support.job.sample;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.base.module.support.job.core.SmartJob;
import net.lab1024.sa.base.module.support.rule.domain.entity.CepEntity;
import net.lab1024.sa.base.module.support.rule.service.CepService;
import net.lab1024.sa.base.module.support.yuntuip.domain.form.YuntuIpAddForm;
import net.lab1024.sa.base.module.support.yuntuip.domain.vo.YuntuIpVO;
import net.lab1024.sa.base.module.support.yuntuip.service.YuntuIpService;
import net.lab1024.sa.base.utils.DateUtilsLocal;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 定时任务 - 云图IP白名单更新
 */
@Slf4j
@Service
public class Yuntu implements SmartJob {

    @Autowired
    private YuntuIpService service;
    @Resource
    private CepService cepService;
    // API配置
    private static  String API_URL ;
    private static  String TOKEN ;
    private static  String SPACE ;
    private static  String SUCCESS_WEBHOOK ;
    private static  String ERROR_WEBHOOK ;

    private static  String CODE = "whitelist_yuntu" ;
    // 文件路径
    private static final String EXCEL_FILE;
    private static final String WHITELIST_HISTORY_FILE;

    // OkHttpClient 实例
    private static final OkHttpClient client;

    static {
        String baseDir = System.getProperty("os.name").toLowerCase().contains("win")
                ? "C:/keji/tools/py"
                : "/opt/keji/tools/py";
        EXCEL_FILE = baseDir + "/last_ips.xlsx";
        WHITELIST_HISTORY_FILE = baseDir + "/whitelist_history.xlsx";

        // 配置SSL
        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }
        };

        SSLContext sslContext;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (Exception e) {
            log.error("SSL配置失败", e);
            throw new RuntimeException("SSL配置失败", e);
        }

        client = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(15, TimeUnit.SECONDS)
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                .hostnameVerifier((hostname, session) -> true)
                .build();
    }

    @Override
    public String run(String param) {
        try {

            JSONObject jsonObject = JSONObject.parseObject(param);
            this.API_URL=jsonObject.getString("api_url");
            this.TOKEN=jsonObject.getString("token");
            this.SPACE=jsonObject.getString("space");
            this.SUCCESS_WEBHOOK=jsonObject.getString("success_webhook");
            this.ERROR_WEBHOOK=jsonObject.getString("error_webhook");


            mainProcess();
            return "成功执行" + this.getClassName();
        } catch (Exception e) {
            String errorMsg = "执行云图IP白名单更新失败: " + e.getMessage();
            log.error(errorMsg, e);
            sendWebhook(errorMsg, ERROR_WEBHOOK);
            return "执行失败：" + e.getMessage();
        }
    }

    private void mainProcess() throws IOException {
        try {

            //获取数据库记录
            List<YuntuIpVO> listall = service.listall();

            // 获取api当前IP
            Set<String> currentIps = fetchCurrentIps();
            if (currentIps.isEmpty()) {
                log.error("获取当前IP地址失败，终止流程");
                sendWebhook("获取当前IP地址失败", ERROR_WEBHOOK);
                throw new RuntimeException("获取当前IP地址失败");
            }
            boolean flag = false;
            //数量不一致 进行更新
            if(currentIps.size()!=listall.size()){
               updateips(currentIps);
               flag=true;
            }else{
              //对比ip 存在差异 进行更新
                Map<String, YuntuIpVO> map = listall.stream()
                        .collect(Collectors.toMap(YuntuIpVO::getIp, obj -> obj));
                for (String ip : currentIps) {
                    if (!map.containsKey(ip)) {
                        // 新增IP
                        updateips(currentIps);
                        flag=true;
                      break;
                    }
                }
            }



            // 获取历史IP
            if (flag) {
                StringBuilder msg = new StringBuilder("IP地址变更通知\n");
                msg.append("新增IP地址(").append(currentIps.size()).append("个):\n");
                msg.append(String.join("\n", currentIps + "\n"));
                msg.append(String.join("\n", "rule_code=" + CODE + "|白名单已更新成功"));
            sendWebhook(msg.toString(), SUCCESS_WEBHOOK);
            }
            log.info("流程执行成功，已发送通知");
        } catch (Exception e) {
            String errorMsg = "主流程执行异常: " + e.getMessage();
            log.error(errorMsg, e);
            sendWebhook(errorMsg, ERROR_WEBHOOK);
            throw e;
        }
    }


    public void updateips(Set<String> currentIps){
        service.deleteall();
        for (String yip : currentIps) {
            YuntuIpAddForm addForm = new YuntuIpAddForm();
            addForm.setIp(yip);
            addForm.setCreateTime(LocalDateTime.now());
            addForm.setUpdateTime(LocalDateTime.now());
            service.add(addForm);
        }
        updateRule(currentIps);

    }

    public void updateRule(Set<String> currentIps){
        CepEntity cepEntity = cepService.detailByCode(CODE);
        CepEntity  cepEntitys= new CepEntity();
        if(null == cepEntity){

            cepEntitys.setRuleCode(CODE);
            cepEntitys.setRuleName("云图IP白名单");
            cepEntitys.setRuleDescription("来自于云图的白名单ip 不允许手动修改");
            cepEntitys.setRuleType("SIMPLE");
            cepEntitys.setPriority(10000);
            cepEntitys.setStatus("ACTIVE");
            cepEntitys.setVersion("1.0.0");
            cepEntitys.setCreatedTime(DateUtilsLocal.getCurrentDateTimeStr());
            cepEntitys.setUpdatedTime(DateUtilsLocal.getCurrentDateTimeStr());
            cepEntitys.setCreatedBy("system");
            cepEntitys.setWhite(1);
            cepEntitys.setLogStatus(0);
            StringBuilder str = new StringBuilder();
            str.append("([");
            int i =0 ;
            for (String ip:currentIps){
                i++;
                if(i==currentIps.size()){
                    str.append("'"+ip+"'");
                }else{
                    str.append("'"+ip+"',");
                }


            }
            str.append("]) contains srcIp");
            cepEntitys.setEpl(str.toString());


            cepService.add(cepEntitys);
        }else{


            StringBuilder str = new StringBuilder();
            str.append("([");
            int i =0 ;
            for (String ip:currentIps){
                i++;
                if(i==currentIps.size()){
                    str.append("'"+ip+"'");
                }else{
                    str.append("'"+ip+"',");
                }


            }
            str.append("]) contains srcIp");
            cepEntity.setEpl(str.toString());
            String priority = cepEntity.getVersion();
            cepEntity.setUpdatedBy("system");
            cepEntity.setVersion(incrementVersion(priority));
            cepService.update(cepEntity);
        }

    }


    /**
            * 递增版本号
     * @param currentVersion 当前版本号，格式为 "X.Y.Z"
            * @return 递增后的版本号
     */
    public static String incrementVersion(String currentVersion) {
        // 分割版本号的三部分
        String[] parts = currentVersion.split("\\.");
        if (parts.length != 3) {
            throw new IllegalArgumentException("版本号格式不正确，应为 X.Y.Z 格式");
        }

        try {
            int major = Integer.parseInt(parts[0]);
            int minor = Integer.parseInt(parts[1]);
            int patch = Integer.parseInt(parts[2]);

            // 递增逻辑
            patch++;  // 修订号加1

            if (patch >= 10) {
                patch = 0;
                minor++;

                if (minor >= 10) {
                    minor = 0;
                    major++;
                }
            }

            return major + "." + minor + "." + patch;

        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("版本号包含非数字字符");
        }
    }

    private Set<String> fetchCurrentIps() {
        Set<String> ips = new HashSet<>();
        try {
            Request request = new Request.Builder()
                    .url(API_URL)
                    .addHeader("TOKEN", TOKEN)
                    .addHeader("space", SPACE)
                    .build();

            try (Response response = client.newCall(request).execute()) {
                String responseBody = response.body() != null ? response.body().string() : null;
                log.debug("获取IP响应: {}", responseBody);
                
                if (response.isSuccessful() && responseBody != null) {
                    JSONObject jsonResponse = JSON.parseObject(responseBody);
                    if (jsonResponse.getInteger("code") == 200) {
                        JSONArray data = jsonResponse.getJSONArray("data");
                        for (int i = 0; i < data.size(); i++) {
                            ips.add(data.getJSONObject(i).getString("internet_ip"));
                        }
                    } else {
                        log.error("获取IP失败，API返回错误: {}", jsonResponse);
                    }
                } else {
                    log.error("获取IP请求失败，状态码: {}, 响应: {}", response.code(), responseBody);
                }
            }
        } catch (Exception e) {
            log.error("获取IP异常", e);
        }
        return ips;
    }












    private void sendWebhook(String message, String webhookUrl) {
        try {
            log.info("准备发送Webhook通知: {}...", message.length() > 50 ? message.substring(0, 50) + "..." : message);
            
            JSONObject payload = new JSONObject();
            JSONObject text = new JSONObject();
            text.put("content", message);
            payload.put("msgtype", "text");
            payload.put("text", text);

            String jsonBody = payload.toJSONString();
            log.debug("Webhook请求体: {}", jsonBody);

            RequestBody body = RequestBody.create(
                    MediaType.parse("application/json"), 
                    jsonBody
            );

            Request request = new Request.Builder()
                    .url(webhookUrl)
                    .post(body)
                    .addHeader("Content-Type", "application/json")
                    .build();

            try (Response response = client.newCall(request).execute()) {
                String responseBody = response.body() != null ? response.body().string() : null;
                if (!response.isSuccessful()) {
                    log.error("Webhook发送失败，HTTP状态码: {}, 响应内容: {}", response.code(), responseBody);
                } else {
                    log.info("Webhook通知发送成功, 响应内容: {}", responseBody);
                }
            }
        } catch (Exception e) {
            log.error("Webhook发送失败: {}", e.getMessage(), e);
        }
    }
}
